package storage;

import java.util.Iterator;
import java.util.List;

import common.IGrid;
import simulation.Earth;
import simulation.Sun;
import storage.beans.CellBean;
import storage.beans.Region;

public class SamplingAccuracyInterpreter {
  private int accuracy;
  private int interval;
  private int cellsPerRow;
  private int cellsPerCol;
  private CellBean[][] cellBeanGrid;
  
  public SamplingAccuracyInterpreter(int accuracy) {
    this.accuracy = accuracy;
  }
  
  public CellBean[][] getGrid(List cellBeanList, int cellsPerCol, int cellsPerRow) {
    this.cellsPerCol = cellsPerCol;
    this.cellsPerRow = cellsPerRow;
    interval = getInterval();
    cellBeanGrid = new CellBean[cellsPerCol][cellsPerRow];
    int count = 0;
    Iterator beanItr = cellBeanList.iterator();
    
    if(accuracy >= 50) {      
      for(int y = 0; y < cellsPerCol; y++) {
        for(int x = 0; x < cellsPerRow; x++) {
          if(count++ == interval) {
            count = 0;
          }
          else {
            cellBeanGrid[y][x] = (CellBean) beanItr.next();            
          }
        }
      }
    }
    else {
      for(int y = 0; y < cellsPerCol; y++) {
        for(int x = 0; x < cellsPerRow; x++) {
          if(count++ == interval) {
            cellBeanGrid[y][x] = (CellBean) beanItr.next();
            count = 0;
          }
          else {
            //skip
          }
        }
      }
    }
    return cellBeanGrid;
  }
  
  public CellBean[][] getGrid(IGrid grid) {
    this.cellsPerCol = grid.getHeight();
    this.cellsPerRow = grid.getWidth();
    interval = getInterval();
    cellBeanGrid = new CellBean[cellsPerCol][cellsPerRow];
    int count = 0;
    
    if(accuracy >= 50) {      
      for(int y = 0; y < cellsPerCol; y++) {
        for(int x = 0; x < cellsPerRow; x++) {
          if(count++ == interval) {
            count = 0;
          }
          else {
            Region region = grid.getRegion(x, y);
            double temp = grid.getTemperature(x, y);
            float cellHeight = grid.getCellHeight(x, y);
            cellBeanGrid[y][x] = new CellBean(region, temp, x, y, cellHeight);            
          }
        }
      }
    }
    else {
      for(int y = 0; y < cellsPerCol; y++) {
        for(int x = 0; x < cellsPerRow; x++) {
          if(count++ == interval) {
            Region region = grid.getRegion(x, y);
            double temp = grid.getTemperature(x, y);
            float cellHeight = grid.getCellHeight(x, y);
            cellBeanGrid[y][x] = new CellBean(region, temp, x, y, cellHeight);
            count = 0;
          }
          else {
            //skip
          }
        }
      }
    }
    return cellBeanGrid;
  }
  
  /**
   * The interval returned is interpreted in two different ways depending on the accuracy.
   *  
   * If the accuracy is >= 50, the interval is the number of saves made before one skip occurs.
   * 
   * If the accuracy is < 50, the interval is the number of skips made before one save occurs.
   * 
   * @return the interval, interpreted as described above
   */
  private int getInterval() {
    int totalNumCells = cellsPerCol * cellsPerRow;
    double cellsToSave = (double)accuracy/100 * totalNumCells;
    double totalCellsToSkip = Math.ceil(totalNumCells - cellsToSave);
    if(totalCellsToSkip % 2 == 1)
      totalCellsToSkip += 1;
    
    double interval;
    if(accuracy >= 50) {
      double skipPerRow = totalCellsToSkip / cellsPerCol;
      interval = cellsPerRow / skipPerRow - 1;
    }
    else  {
      double savePerRow = cellsToSave / cellsPerCol;
      interval = cellsPerRow / savePerRow - 1;
    }
    
    return (int)interval;
  }
  
  public String getGridString(IGrid grid) {
    CellBean[][] cellGrid = getGrid(grid);
    
    String s = "Accuracy = "+accuracy+"%   Interval: "+interval+"\n"+cellGrid.toString()+"\n";
    for(int y = 0; y < cellGrid.length; y++) {
      for(int x = 0; x < cellGrid[y].length; x++) {
        CellBean cb = cellGrid[y][x];
        if(cb == null)
          s += "null";
        else
          s += cb.getTemperature();
        s += " | ";
      }
      s += "\n";
    }
    return s;
  }
  
  public static void main(String[] args) {
    int accuracy = 20;
    SamplingAccuracyInterpreter ai = new SamplingAccuracyInterpreter(accuracy);
    IGrid grid = new Earth(45, 200, new Sun(0, 0d, 0d));
    System.out.println(ai.getGridString(grid));
    
    accuracy = 85;
    ai = new SamplingAccuracyInterpreter(accuracy);
    grid = new Earth(45, 200, new Sun(0, 0d, 0d));
    System.out.println(ai.getGridString(grid));
  }

}
